package com.zjl.springbatch.job.config;

import com.zjl.springbatch.domain.Employee;
import com.zjl.springbatch.job.listener.DBToDBJobListener;
import com.zjl.springbatch.job.partitioner.DBToDBPartitioner;
import com.zjl.springbatch.util.OutColour;
import com.zjl.学习.第06章_块步骤_读操作写.User;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.batch.MyBatisBatchItemWriter;
import org.mybatis.spring.batch.MyBatisPagingItemReader;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.configuration.annotation.JobBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepBuilderFactory;
import org.springframework.batch.core.configuration.annotation.StepScope;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.partition.PartitionHandler;
import org.springframework.batch.core.partition.support.TaskExecutorPartitionHandler;
import org.springframework.batch.item.ItemProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * 配置分区作业
 * 将 临时表数据读入 非临时表中
 */
@Configuration
public class DBToDBJobConfig {
    @Autowired
    private JobBuilderFactory jobBuilderFactory;
    @Autowired
    private StepBuilderFactory stepBuilderFactory;
    @Autowired
    private SqlSessionFactory sqlSessionFactory;//数据源

    //从步奏-reader
    @Bean
    @StepScope//启动才使用
    public MyBatisPagingItemReader<Employee> dbToItemReader(
            @Value("#{stepExecutionContext[from]}") Integer from,
            @Value("#{stepExecutionContext[to]}") Integer to,
            @Value("#{stepExecutionContext[range]}") Integer range
    ){
        OutColour.out.printlnGreen("分步奏开始【from:",from,"\tto:",to,"\trange:",range,"】");
        MyBatisPagingItemReader<Employee> itemReader =
                new MyBatisPagingItemReader<>();
        itemReader.setSqlSessionFactory(sqlSessionFactory);
        itemReader.setPageSize(1000);//每页 1000
        //指定  sql
        itemReader.setQueryId("com.zjl.springbatch.mapper.EmployeeMapper.selectTempForList");

        Map<String,Object> map = new HashMap<>();
        map.put("from",from);
        map.put("to",to);
        map.put("range",range);
        itemReader.setParameterValues(map);

        return itemReader;
    }

    //从步奏-writer
    @Bean
    public MyBatisBatchItemWriter<Employee> dbToDBItemWriter(){
        MyBatisBatchItemWriter<Employee> itemWriter = new MyBatisBatchItemWriter<>();
        //设置数据源
        itemWriter.setSqlSessionFactory(sqlSessionFactory);

        //指定要执行的sql语句
        itemWriter.setStatementId("com.zjl.springbatch.mapper.EmployeeMapper.save");


        return itemWriter;
    }
    @Bean
    public ItemProcessor<Employee,Employee> dbToDBItemProcessor(){
        return new ItemProcessor<Employee, Employee>() {
            @Override
            public Employee process(Employee employee) throws Exception {
                OutColour.out.printlnRed("--------------处理完毕-------------");
                return employee;
            }
        };
    }


    @Bean
    public Step dbToDBDivStep(){
        return stepBuilderFactory.get("dbToDBDivStep")
                //每次读取数据 个数
                .<Employee, Employee>chunk(1000)
                .reader(dbToItemReader(null,null,null))//读
                .processor(dbToDBItemProcessor())
                .writer(dbToDBItemWriter())//写
//                .taskExecutor(new SimpleAsyncTaskExecutor())//异步处理
                .build();
    }
    //分区器
    @Bean
    public DBToDBPartitioner dbToDBPartitioner(){
        return new DBToDBPartitioner();
    }

    //分区处理器
    @Bean
    public PartitionHandler dbToDBPartitionHandler(){
        TaskExecutorPartitionHandler handler
                = new TaskExecutorPartitionHandler();
        handler.setGridSize(50);
        handler.setTaskExecutor(new SimpleAsyncTaskExecutor());//异步处理
        handler.setStep(dbToDBDivStep());//放入分步奏
        try {
            handler.afterPropertiesSet();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return handler;
    }
    //主步奏
    @Bean
    public Step dbToDBMainStep(){
        return stepBuilderFactory.get("dbToDBMainStep")
                .partitioner(dbToDBDivStep().getName(),dbToDBPartitioner())
                .partitionHandler(dbToDBPartitionHandler())
                .build();
    }
    @Autowired
    private DBToDBJobListener dbToDBJobListener;
    @Bean
    public Job dbToDBJob() {
        return jobBuilderFactory.get("dbToDBJob")
                .start(dbToDBMainStep())//可添加多个 Step
                //启动多次,启动多次的原理就是在每次程序启动，都会从1开始设置一个Long 累加，
                // 导致  识别参数  不一致，认为可以 不一致的执行
                .incrementer(new RunIdIncrementer())
                .listener(dbToDBJobListener)//添加Listener  也就是job的执行前 和执行后
                .build();
    }

}
